import axios, { type AxiosRequestHeaders } from "axios";
import pinia from "@/stores/index";
import { useUserInfoStore } from "../stores/userInfo";
const getApiAddress = ()=>{
  if(import.meta.env.MODE === "development"){
    return "/api"
  }else{
    return window.apiAddress.baseUrl
  }
}
const request = axios.create({
  baseURL:getApiAddress(),
});
class EventEmitter{
  public events:Record<string,Function[]> = {}
  constructor(){
      this.events = {}
  }
  on(type:string,cbres:Function,cbrej:Function){
      if(!this.events[type]){
          this.events[type] = [[cbres,cbrej]]
      }else{
          this.events[type].push([cbres,cbrej])
      } 
  }
  emit(type:string,res:any,ansType:string){
     if(!this.events[type]){
      return
     }
     this.events[type].forEach(([cbres,cbrej])=>{
      if(ansType === "resolve"){
          cbres(res)
      }else{
          cbrej(res)
      }
     })
  }
}

const generateReqKey = (config:any)=>{
  const {method,url,params,data} = config;
  return [method,url,JSON.stringify(params),JSON.stringify(data)].join('&');
}
const pendingRequest = new Set();
const ev:EventEmitter = new EventEmitter();
const handleSuccessResponse_limit = (response:any)=>{
   const reqKey = response.config.pendKey
   if(pendingRequest.has(reqKey)){
     let x= null
     try {
       x = JSON.parse(JSON.stringify(response))
     } catch (error) {
       x = response
     }
     pendingRequest.delete(reqKey)
     ev.emit(reqKey,x,'resolve')
     delete ev.events[reqKey]
   }
}
function handleErrorResponse_limit(error){
  if(error.type && error.type === 'limiteResSuccess') {
      return Promise.resolve(error.val)
  }else if(error.type && error.type === 'limiteResError'){
      return Promise.reject(error.val)
  }else{
      const reqKey = error.config.pendKey
      if(pendingRequest.has(reqKey)){
          let x = null
          try {
              x = JSON.parse(JSON.stringify(error))
            }catch(e) {
              x = error
            }
            pendingRequest.delete(reqKey)
            ev.emit(reqKey, x, 'reject')
            delete ev.events[reqKey]
      }
  }
  return Promise.reject(error)
}
const fileUploadUrls=['/ota/file_upload']
request.interceptors.request.use(async (config:any) => {
    const userInfoStore = useUserInfoStore(pinia)
    const token = userInfoStore.token
    if(token){
        (config.headers as AxiosRequestHeaders )['Authorization'] ='Bearer '+ token
      }
    if(!fileUploadUrls.includes(config.url)){
      config.headers['Content-Type'] = 'application/json;charset=UTF-8'
     }
     let reqKey = generateReqKey(config)
     if(pendingRequest.has(reqKey)){       
      let res = null
      try {
          res = await new Promise((resolve, reject) => {
              ev.on(reqKey, resolve, reject)
          })       
          return Promise.reject({
              type: 'limiteResSuccess',
              val: res
          })
      } catch (error) {
          return Promise.reject({
              type: 'limiteResError',
              val: res
          })
       }
    }else{
      config.pendKey = reqKey
      pendingRequest.add(reqKey)    
   }
    return config;
});
request.interceptors.response.use(
  async (response:any) => {
    const res = response.data
    handleSuccessResponse_limit(response)
    if (res.code !== 200) {
      // ElNotificationFn('error',res.message);
      console.log(res.message,"error");      
      return Promise.reject(new Error(res.message || "Error"));
    }
    return res;
  },
  (error:any) => {
   return handleErrorResponse_limit(error)
  }
);

export default request;
